﻿using Moq;
using NUnit.Framework;
using SessionHunter.DataAccess;

namespace SessionHunter.UnitTests.DataAccess
{
    [TestFixture]
    public class TestConnectionStringRepository
    {
        private const string _integratedAuthConnectionString = "data source=localhost\\sqlExpress; initial catalog=ASPState;trusted_connection=true";
        private const string _sqlAuthConnectionString = "data source=localhost\\sqlExpress; initial catalog=ASPState;User ID=testuser;Password=fakepassword";

        [Test]
        public void GetConnectionStringValues_ParseSQLAuth_CorrectParsing()
        {
            // Arrange
            var repo = new Mock<ConnectionStringRepository>();
            repo.Setup(mock => mock.GetConnectionString()).Returns(_sqlAuthConnectionString);

            string server = null;
            string database = null;
            bool isEncrypted = false;
            bool isIntegratedAuth = false;
            string userName = null;

            // Act
            repo.Object.GetConnectionStringValues(out server, out database, out isEncrypted, out isIntegratedAuth, out userName);

            // Assert
            Assert.AreEqual("localhost\\sqlExpress", server);
            Assert.AreEqual("ASPState", database);
            Assert.AreEqual(false, isEncrypted);
            Assert.AreEqual(false, isIntegratedAuth);
            Assert.AreEqual("testuser", userName);
        }

        [Test]
        public void GetConnectionStringValues_ParseIntegratedAuth_CorrectParsing()
        {
            // Arrange
            var repo = new Mock<ConnectionStringRepository>();
            repo.Setup(mock => mock.GetConnectionString()).Returns(_integratedAuthConnectionString);

            string server = null;
            string database = null;
            bool isEncrypted = false;
            bool isIntegratedAuth = false;
            string userName = null;

            // Act
            repo.Object.GetConnectionStringValues(out server, out database, out isEncrypted, out isIntegratedAuth, out userName);

            // Assert
            Assert.AreEqual("localhost\\sqlExpress", server);
            Assert.AreEqual("ASPState", database);
            Assert.AreEqual(false, isEncrypted);
            Assert.AreEqual(true, isIntegratedAuth);
            Assert.IsNull(userName);
        }

        [Test]
        public void GetConnectionStringValues_TestEmptyString_ServerIsNull()
        {
            // Arrange
            var repo = new Mock<ConnectionStringRepository>();
            repo.Setup(mock => mock.GetConnectionString()); // returns null

            string server = null;
            string database = null;
            bool isEncrypted = false;
            bool isIntegratedAuth = false;
            string userName = null;

            // Act
            repo.Object.GetConnectionStringValues(out server, out database, out isEncrypted, out isIntegratedAuth, out userName);

            // Assert
            Assert.IsNull(server, "Server is not null with a blank connection string");
        }


        /// <summary>
        /// Tests to make sure we are getting a connection string out
        /// </summary>
        [Test]
        public void GetConnectionString_TestConnectionString_NotEmpty()
        {
            var repo = new ConnectionStringRepository();
            Assert.Greater(repo.GetConnectionString().Length, 0, "No connection string returned");
        }

        [Test]
        public void SaveConnectionStringValues_SaveIntegratedAuth_Success()
        {
            // Arrange
            string connectionString = null;
            var repo = new Mock<ConnectionStringRepository>();
            repo.Setup(mock => mock.ApplyChangesToConfigFile(It.IsAny<string>(), false)).Callback((string s, bool b) =>
                {
                    connectionString = s;
                });

            string server = "myServer";
            string database = "myDatabase";
            bool isEncrypted = false;
            bool isIntegratedAuth = true;
            string userName = null;
            string password = null;

            // Act
            repo.Object.SaveConnectionStringValues(server, database, isEncrypted, isIntegratedAuth, userName, password);

            // Assert
            Assert.AreEqual("Data Source=myServer;Initial Catalog=myDatabase;Integrated Security=True", connectionString);
        }

        [Test]
        public void SaveConnectionStringValues_SaveSqlAuth_Success()
        {
            // Arrange
            string connectionString = null;
            var repo = new Mock<ConnectionStringRepository>();
            repo.Setup(mock => mock.ApplyChangesToConfigFile(It.IsAny<string>(), false)).Callback((string s, bool b) =>
            {
                connectionString = s;
            });

            string server = "myServer";
            string database = "myDatabase";
            bool isEncrypted = false;
            bool isIntegratedAuth = false;
            string userName = "BruceWayne";
            string password = "IAmBatman";

            // Act
            repo.Object.SaveConnectionStringValues(server, database, isEncrypted, isIntegratedAuth, userName, password);

            // Assert
            Assert.AreEqual("Data Source=myServer;Initial Catalog=myDatabase;User ID=BruceWayne;Password=IAmBatman", connectionString);
        }

        /// <summary>
        /// Return the connection string, which is stored in settings
        /// </summary>
        public static string GetConnectionString
        {
            get
            {
                var repo = new ConnectionStringRepository();
                return repo.GetConnectionString();
            }
        }
    }
}
